package com.ukefu.webim.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.locks.Lock;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import com.hazelcast.aggregation.Aggregator;
import com.hazelcast.aggregation.Aggregators;
import com.hazelcast.core.IMap;
import com.hazelcast.query.PagingPredicate;
import com.hazelcast.query.Predicates;
import com.hazelcast.query.SqlPredicate;
import com.ukefu.core.UKDataContext;
import com.ukefu.util.freeswitch.model.CallCenterAgent;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.quene.AgentCallOutFilterPredicate;
import com.ukefu.webim.service.quene.AiCallOutFilterPredicate;
import com.ukefu.webim.service.quene.AiUserFilterPredicate;
import com.ukefu.webim.service.quene.CallCenterAgentOrgiFilterPredicate;
import com.ukefu.webim.service.quene.CallCenterAgentReadyOrgiFilterPredicate;
import com.ukefu.webim.service.quene.CallCenterInCallOrgiActidFilterPredicate;
import com.ukefu.webim.service.quene.CallCenterInCallOrgiFilterPredicate;
import com.ukefu.webim.service.quene.CallCenterPreviewActidFilterPredicate;
import com.ukefu.webim.service.quene.ForecastAgentFilterPredicate;
import com.ukefu.webim.service.quene.ForecastAllAgentFilterPredicate;
import com.ukefu.webim.service.quene.ForecastCallOutFilterPredicate;
import com.ukefu.webim.service.quene.StatusEventFilterPredicate;
import com.ukefu.webim.service.quene.StatusEventQueneFilterPredicate;
import com.ukefu.webim.service.repository.CallOutNamesRepository;
import com.ukefu.webim.web.model.AgentReport;
import com.ukefu.webim.web.model.AiUser;
import com.ukefu.webim.web.model.CallOutNames;
import com.ukefu.webim.web.model.StatusEvent;

@Service("calloutquene")
public class CallOutQuene {
	/**
	 * 为外呼坐席分配名单
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<CallCenterAgent> service(){
		List<CallCenterAgent> agentList = new ArrayList<CallCenterAgent>();
		if(CacheHelper.getCallCenterAgentCacheBean()!=null && CacheHelper.getCallCenterAgentCacheBean().getCache()!=null) {
			PagingPredicate<String, CallCenterAgent> pagingPredicate = new PagingPredicate<String, CallCenterAgent>(  new SqlPredicate( "offline == false and workstatus = 'callout'") , 10 ) ;
			agentList.addAll(((IMap<String , CallCenterAgent>) CacheHelper.getCallCenterAgentCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return agentList ;
	}
	
	/**
	 * 为外呼坐席分配名单
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<CallCenterAgent> service(String sip){
		List<CallCenterAgent> agentList = new ArrayList<CallCenterAgent>();
		if(CacheHelper.getCallCenterAgentCacheBean()!=null && CacheHelper.getCallCenterAgentCacheBean().getCache()!=null) {
			PagingPredicate<String, CallCenterAgent> pagingPredicate = new PagingPredicate<String, CallCenterAgent>(  new SqlPredicate( "siptrunk = '"+sip+"'") , 10 ) ;
			agentList.addAll(((IMap<String , CallCenterAgent>) CacheHelper.getCallCenterAgentCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return agentList ;
	}
	
	/**
	 * 预测式外呼坐席
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<CallCenterAgent> forecast(String forecastid){
		List<CallCenterAgent> agentList = new ArrayList<CallCenterAgent>();
		if(CacheHelper.getCallCenterAgentCacheBean()!=null && CacheHelper.getCallCenterAgentCacheBean().getCache()!=null) {
			PagingPredicate<String, CallCenterAgent> pagingPredicate = new PagingPredicate<String, CallCenterAgent>( Predicates.like("forecastvalue", forecastid) , 1 ) ;
			agentList.addAll(((IMap<String , CallCenterAgent>) CacheHelper.getCallCenterAgentCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return agentList ;
	}
	
	/**
	 * 预测式外呼坐席
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<CallCenterAgent> forecastAgent(String forecastid){
		List<CallCenterAgent> agentList = new ArrayList<CallCenterAgent>();
		if(CacheHelper.getCallCenterAgentCacheBean()!=null && CacheHelper.getCallCenterAgentCacheBean().getCache()!=null) {
			PagingPredicate<String, CallCenterAgent> pagingPredicate = new PagingPredicate<String, CallCenterAgent>( new SqlPredicate( "forecastvalue like '%"+forecastid+"%' AND offline == false AND workstatus ='"+UKDataContext.WorkStatusEnum.CALLOUT.toString()+"'" )   , 1 ) ;
			agentList.addAll(((IMap<String , CallCenterAgent>) CacheHelper.getCallCenterAgentCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return agentList ;
	}
	
	
	/**
	 * 获得 当前服务状态
	 * @param orgi
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static AgentReport getCallCenterAgentReport(String orgi){
		/**
		 * 统计当前在线的坐席数量
		 */
		AgentReport report = new AgentReport() ;
		IMap callCenterAgentMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		Long agents = (Long) callCenterAgentMap.aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new CallCenterAgentOrgiFilterPredicate(orgi)) ;
		report.setAgents(agents.intValue());
		
		Long readyAgent = (Long) callCenterAgentMap.aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new CallCenterAgentReadyOrgiFilterPredicate(orgi)) ;
		report.setReadyagents(readyAgent.intValue());
		
		Long inCallAgent = (Long) callCenterAgentMap.aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new CallCenterInCallOrgiFilterPredicate(orgi)) ;
		report.setIncall(inCallAgent.intValue());
		
		report.setOrgi(orgi);
		return report;
	}
	
	/**
	 * 为外呼坐席分配名单
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<CallCenterAgent> extention(String extno){
		List<CallCenterAgent> agentList = new ArrayList<CallCenterAgent>();
		if(CacheHelper.getCallCenterAgentCacheBean()!=null && CacheHelper.getCallCenterAgentCacheBean().getCache()!=null) {
			PagingPredicate<String, CallCenterAgent> pagingPredicate = new PagingPredicate<String, CallCenterAgent>(  new SqlPredicate( "offline == false and extno = '"+extno+"'") , 10 ) ;
			agentList.addAll(((IMap<String , CallCenterAgent>) CacheHelper.getCallCenterAgentCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return agentList ;
	}
	
	/**
	 * 查找就绪的坐席
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<CallCenterAgent> agents(){
		List<CallCenterAgent> agentList = new ArrayList<CallCenterAgent>();
		if(CacheHelper.getInstance() != null && CacheHelper.getCallCenterAgentCacheBean()!=null && CacheHelper.getCallCenterAgentCacheBean().getCache()!=null) {
			PagingPredicate<String, CallCenterAgent> pagingPredicate = new PagingPredicate<String, CallCenterAgent>(  new SqlPredicate( "status = '"+UKDataContext.AgentStatusEnum.READY.toString()+"' and upd < "+(System.currentTimeMillis() - 60 * 1000)) , 20 ) ;
			agentList.addAll(((IMap<String , CallCenterAgent>) CacheHelper.getCallCenterAgentCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return agentList ;
	}
	
	public static int countAiCallOut(String orgi) {
		/**
		 * 统计当前在线的坐席数量
		 */
		return UKDataContext.getContext().getBean(CallOutNamesRepository.class).countByOrgiAndCalltype(orgi , UKDataContext.CallOutType.AI.toString()) ;
	}
	
	public static int countAiCallOut(String orgi,String ownerai) {
		/**
		 * 统计当前在线的坐席数量
		 */
		int count = 0 ;
		if(!StringUtils.isBlank(ownerai)) {
			count = UKDataContext.getContext().getBean(CallOutNamesRepository.class).countByOrgiAndOwnerai(orgi, ownerai); ;
		}else {
			count = countAiCallOut(orgi) ;
		}
		return count;
	}
	
	public static int countAiCallOut(String orgi,String ownerai,String actid) {
		int count = 0 ;
		if(!StringUtils.isBlank(actid)) {
			count = UKDataContext.getContext().getBean(CallOutNamesRepository.class).countByOrgiAndActid(orgi, actid) ;
		}else {
			count = countAiCallOut(orgi , ownerai) ;
		}
		return count;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countAgentCallOut(String orgi) {
		/**
		 * 统计当前在线的坐席数量
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallOutCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallOutNames>>count(), new AgentCallOutFilterPredicate(orgi)) ;
		return names!=null ? names.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countAgentCallOut(String orgi,String actid) {
		/**
		 * 统计当前在线的坐席数量
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallOutCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallOutNames>>count(), new AgentCallOutFilterPredicate(orgi,actid)) ;
		return names!=null ? names.intValue() : 0 ;
	}
	
	
	/**
	 * 外呼监控，包含机器人和人工两个部分
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<CallOutNames> callOutNames(String calltype , int p , int ps){
		List<CallOutNames> callOutNamesList = new ArrayList<CallOutNames>();
		if(CacheHelper.getCallOutCacheBean()!=null && CacheHelper.getCallOutCacheBean().getCache()!=null) {
			PagingPredicate<String, CallOutNames> pagingPredicate = new PagingPredicate<String, CallOutNames>(  new SqlPredicate( "calltype = '"+calltype+"'") , 10 ) ;
			pagingPredicate.setPage(p);
			callOutNamesList.addAll(((IMap<String , CallOutNames>) CacheHelper.getCallOutCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return callOutNamesList ;
	}
	
	/**
	 * 外呼监控，包含机器人和人工两个部分
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<CallOutNames> callOutNamesByOrgi(String orgi , int p , int ps){
		List<CallOutNames> callOutNamesList = new ArrayList<CallOutNames>();
		if(CacheHelper.getCallOutCacheBean()!=null && CacheHelper.getCallOutCacheBean().getCache()!=null) {
			PagingPredicate<String, CallOutNames> pagingPredicate = new PagingPredicate<String, CallOutNames>(  new SqlPredicate( "orgi = '"+orgi+"'") , 10 ) ;
			pagingPredicate.setPage(p);
			callOutNamesList.addAll(((IMap<String , CallOutNames>) CacheHelper.getCallOutCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return callOutNamesList ;
	}
	
	/**
	 * 为外呼坐席分配名单
	 * @param agentStatus
	 */
	@SuppressWarnings("unchecked")
	public static List<StatusEvent> callAgent(String agent){
		List<StatusEvent> statusEventList = new ArrayList<StatusEvent>();
		if(CacheHelper.getCallCenterCacheBean()!=null && CacheHelper.getCallCenterCacheBean().getCache()!=null) {
			PagingPredicate<String, StatusEvent> pagingPredicate = new PagingPredicate<String, StatusEvent>(  new SqlPredicate( "agent = '"+agent+"'") , 10 ) ;
			statusEventList.addAll(((IMap<String , StatusEvent>) CacheHelper.getCallCenterCacheBean().getCache()).values(pagingPredicate)) ;
		}
		return statusEventList ;
	}
	
	/**
	 * 当前通话数量
	 * @param agentStatus
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int calls(String orgi){
		IMap statusEventMap = (IMap<String, Object>) CacheHelper.getCallCenterCacheBean().getCache() ;
		Long calls = (Long) statusEventMap.aggregate(Aggregators.<Map.Entry<String, StatusEvent>>count(), new StatusEventFilterPredicate(orgi)) ;
		return calls!=null ? calls.intValue() : 0 ;
	}
	
	/**
	 * 排队数量
	 * @param agentStatus
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int inquenecalls(String orgi){
		IMap statusEventMap = (IMap<String, Object>) CacheHelper.getCallCenterCacheBean().getCache() ;
		Long calls = (Long) statusEventMap.aggregate(Aggregators.<Map.Entry<String, StatusEvent>>count(), new StatusEventQueneFilterPredicate(orgi)) ;
		return calls!=null ? calls.intValue() : 0 ;
	}
	
	
	public static int countForecastCallOut(String orgi) {
		/**
		 * 统计当前在线的坐席数量
		 */
		return UKDataContext.getContext().getBean(CallOutNamesRepository.class).countByOrgiAndCalltype(orgi , UKDataContext.CallOutType.FORECAST.toString()) ;
	}

	public static int countForecastCallOut(String orgi,String ownerforecast) {
		/**
		 * 统计当前在线的坐席数量
		 */
		return UKDataContext.getContext().getBean(CallOutNamesRepository.class).countByOrgiAndOwnerforecast(orgi, ownerforecast);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countForecastAgent(String orgi,String ownerforecast) {
		/**
		 * 统计当前在线的坐席数量
		 */
		IMap agentMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		Long agents = (Long) agentMap .aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new ForecastAgentFilterPredicate(orgi,ownerforecast)) ;
		return agents !=null ? agents.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countForecastAllAgentForecast(String orgi,String ownerforecast) {
		/**
		 * 统计当前在线的坐席数量
		 */
		IMap agentMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		Long agents = (Long) agentMap .aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new ForecastAllAgentFilterPredicate(orgi,ownerforecast)) ;
		return agents !=null ? agents.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countCallCenterAgent(String orgi) {
		/**
		 * 统计当前总坐席数量
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new CallCenterAgentOrgiFilterPredicate(orgi)) ;
		return names!=null ? names.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countCallCenterAgent(String orgi,String actid) {
		/**
		 * 统计当前总坐席数量
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new CallCenterAgentOrgiFilterPredicate(orgi,actid)) ;
		return names!=null ? names.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countIncallCallCenterAgent(String orgi,String actid) {
		/**
		 * 统计当前通话坐席数量
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new CallCenterInCallOrgiFilterPredicate(orgi,actid)) ;
		return names!=null ? names.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countIncallActidCallCenterAgent(String orgi,String actid) {
		/**
		 * actid非空的所有人工坐席
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new CallCenterInCallOrgiActidFilterPredicate(orgi,actid)) ;
		return names!=null ? names.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static double avgWaittimeCallCenterAgent(final String orgi,final String actid) {
		/**
		 * 空闲坐席等待平均时长   当前时间-upd字段
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		@SuppressWarnings("serial")
		double avgSalary = (double) callOutMap.aggregate(new Aggregator<Map.Entry<String, CallCenterAgent>, Double>(){
			protected long sum;
	        protected long count;
			@Override
			public void accumulate(Entry<String, CallCenterAgent> input) {
				boolean flag = !UKDataContext.AgentStatusEnum.INCALL.toString().equals(input.getValue().getStatus()) && input.getValue().getUpd() != 0
						&& input.getValue().isOffline()==false && input.getValue().getWorkstatus().equals(UKDataContext.WorkStatusEnum.CALLOUT.toString())
						&& !StringUtils.isBlank(orgi) && orgi.equals(input.getValue().getOrgi());
				if (flag) {
					count++;
					sum += ((System.currentTimeMillis()-input.getValue().getUpd())/1000);
				}
			}

			@Override
			public void combine(Aggregator aggregator) {
				this.sum += this.getClass().cast(aggregator).sum;
	            this.count += this.getClass().cast(aggregator).count;
			}

			@Override
			public Double aggregate() {
				if (count == 0) {
	                return 0.0;
	            }
	            return ((double) sum / (double) count);
			}
			
		});
		return avgSalary;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static long maxWaittimeCallCenterAgent(final String orgi,final String actid) {
		/**
		 * 空闲坐席最大等待时长   当前时间-upd字段
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		@SuppressWarnings("serial")
		long avgSalary = (long) callOutMap.aggregate(new Aggregator<Map.Entry<String, CallCenterAgent>, Long>(){
			protected long max = 0;
			@Override
			public void accumulate(Entry<String, CallCenterAgent> input) {
				boolean flag = !UKDataContext.AgentStatusEnum.INCALL.toString().equals(input.getValue().getStatus()) && input.getValue().getUpd() != 0
						&& input.getValue().isOffline()==false && input.getValue().getWorkstatus().equals(UKDataContext.WorkStatusEnum.CALLOUT.toString())
						&& !StringUtils.isBlank(orgi) && orgi.equals(input.getValue().getOrgi());
				if (flag) {
					long curr = (System.currentTimeMillis()-input.getValue().getUpd())/1000;
					if (max < curr) {
						max = curr ;
					}
				}
			}

			@Override
			public void combine(Aggregator aggregator) {
				this.max += this.getClass().cast(aggregator).max;
			}

			@Override
			public Long aggregate() {
	            return max;
			}
			
		});
		return avgSalary;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static long sumIncalltimeCallCenterAgent(final String orgi,final String actid) {
		/**
		 * 坐席通话总时长
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		@SuppressWarnings("serial")
		long sumSalary = (long) callOutMap.aggregate(new Aggregator<Map.Entry<String, CallCenterAgent>, Long>(){
			protected long sum = 0;
			@Override
			public void accumulate(Entry<String, CallCenterAgent> input) {
				boolean flag = UKDataContext.AgentStatusEnum.INCALL.toString().equals(input.getValue().getStatus()) && input.getValue().getUpdatetime() != null
								&& !StringUtils.isBlank(orgi) && orgi.equals(input.getValue().getOrgi());
				if (flag) {
					sum += (System.currentTimeMillis()-input.getValue().getUpdatetime().getTime())/1000;
				}
			}

			@Override
			public void combine(Aggregator aggregator) {
				this.sum += this.getClass().cast(aggregator).sum;
			}

			@Override
			public Long aggregate() {
	            return sum;
			}
			
		});
		return sumSalary;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static long sumIncalltimeCallOutNames(final String orgi,final String actid) {
		/**
		 * 机器人通话总时长
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallOutCacheBean().getCache() ;
		@SuppressWarnings("serial")
		long sumSalary = (long) callOutMap.aggregate(new Aggregator<Map.Entry<String, CallOutNames>, Long>(){
			protected long sum = 0;
			@Override
			public void accumulate(Entry<String, CallOutNames> input) {
				boolean flag = UKDataContext.AgentStatusEnum.INCALL.toString().equals(input.getValue().getCallstatus()) && input.getValue().getAnswertime() != 0
								&& !StringUtils.isBlank(orgi) && orgi.equals(input.getValue().getOrgi());
				if (!StringUtils.isBlank(actid)) {
					flag = flag && input.getValue().getActid()!=null && input.getValue().getActid().equals(actid);
				}
				if (flag) {
					sum += (System.currentTimeMillis()-input.getValue().getAnswertime())/1000;
				}
			}

			@Override
			public void combine(Aggregator aggregator) {
				this.sum += this.getClass().cast(aggregator).sum;
			}

			@Override
			public Long aggregate() {
	            return sum;
			}
			
		});
		return sumSalary;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static double avgIncalltimeCallOutNames(final String orgi,final String actid) {
		/**
		 * 机器人通话平均时长
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallOutCacheBean().getCache() ;
		@SuppressWarnings("serial")
		double avgSalary = (double) callOutMap.aggregate(new Aggregator<Map.Entry<String, CallOutNames>, Double>(){
			protected long sum;
	        protected long count;
			@Override
			public void accumulate(Entry<String, CallOutNames> input) {
				boolean flag = UKDataContext.AgentStatusEnum.INCALL.toString().equals(input.getValue().getCallstatus()) && input.getValue().getAnswertime() != 0
								&& !StringUtils.isBlank(orgi) && orgi.equals(input.getValue().getOrgi());
				if (!StringUtils.isBlank(actid)) {
					flag = flag && input.getValue().getActid()!=null && input.getValue().getActid().equals(actid);
				}
				if (flag) {
					count++;
					sum += (System.currentTimeMillis()-input.getValue().getAnswertime())/1000;
				}
			}

			@Override
			public void combine(Aggregator aggregator) {
				this.sum += this.getClass().cast(aggregator).sum;
	            this.count += this.getClass().cast(aggregator).count;
			}

			@Override
			public Double aggregate() {
				if (count == 0) {
	                return 0.0;
	            }
	            return ((double) sum / (double) count);
			}
			
		});
		return avgSalary;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static long sumRingtimeCallCenterCacheBean(String orgi,final String actid) {
		/**
		 * 机器人振铃总时长
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterCacheBean().getCache() ;
		@SuppressWarnings("serial")
		long sumSalary = (long) callOutMap.aggregate(new Aggregator<Map.Entry<String, StatusEvent>, Long>(){
			protected long sum = 0;
			@Override
			public void accumulate(Entry<String, StatusEvent> input) {
				boolean flag =  input.getValue().isAi() && input.getValue().getRingduration() != 0;
				if (!StringUtils.isBlank(actid)) {
					flag = flag && input.getValue().getActid()!=null && input.getValue().getActid().equals(actid);
				}
				if (flag) {
					sum += input.getValue().getRingduration()/1000;
				}
			}

			@Override
			public void combine(Aggregator aggregator) {
				this.sum += this.getClass().cast(aggregator).sum;
			}

			@Override
			public Long aggregate() {
	            return sum;
			}
			
		});
		return sumSalary;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static double avgRingtimeCallCenterCacheBean(String orgi,final String actid) {
		/**
		 * 机器人振铃平均时长
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterCacheBean().getCache() ;
		@SuppressWarnings("serial")
		double avgSalary = (double) callOutMap.aggregate(new Aggregator<Map.Entry<String, StatusEvent>, Double>(){
			protected long sum;
	        protected long count;
			@Override
			public void accumulate(Entry<String, StatusEvent> input) {
				boolean flag = input.getValue().isAi() && input.getValue().getRingduration() != 0;
				if (!StringUtils.isBlank(actid)) {
					flag = flag && input.getValue().getActid()!=null && input.getValue().getActid().equals(actid);
				}
				if (flag) {
					count++;
					sum += input.getValue().getRingduration()/1000;
				}
			}

			@Override
			public void combine(Aggregator aggregator) {
				this.sum += this.getClass().cast(aggregator).sum;
	            this.count += this.getClass().cast(aggregator).count;
			}

			@Override
			public Double aggregate() {
				if (count == 0) {
	                return 0.0;
	            }
	            return ((double) sum / (double) count);
			}
			
		});
		return avgSalary;
	}
	/**
	 * 更新坐席当前服务中的用户状态，需要分布式锁
	 * @param agentStatus
	 * @param agentUser
	 * @param orgi
	 */
	public synchronized static CallCenterAgent updateAgentStatus(String forecastid ,String orgi){
		CallCenterAgent agent = null ;
		Lock lock = CacheHelper.getCallCenterAgentCacheBean().getLock("AgentLOCK", orgi) ;
		lock.lock();
		try{
			List<CallCenterAgent> agents = forecastAgent(forecastid) ;
			if(agents!=null && agents.size() > 0) {
				agent = agents.get(0) ;
				agent.setWorkstatus(UKDataContext.WorkStatusEnum.PREVIEW.toString());
				CacheHelper.getCallCenterAgentCacheBean().put(agent.getUserid(), agent, orgi);
			}
		}finally{
			lock.unlock();
		}
		return agent;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countPreviewingCallCenterAgent(String orgi,String actid) {
		/**
		 * 正在预览的坐席
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallCenterAgent>>count(), new CallCenterPreviewActidFilterPredicate(orgi,actid)) ;
		return names!=null ? names.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static long countkongxianCallCenterAgent(final String orgi,final String actid) {
		/**
		 * 空闲坐席最大等待时长   当前时间-upd字段
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallCenterAgentCacheBean().getCache() ;
		@SuppressWarnings("serial")
		long avgSalary = (long) callOutMap.aggregate(new Aggregator<Map.Entry<String, CallCenterAgent>, Long>(){
			protected long count = 0;
			@Override
			public void accumulate(Entry<String, CallCenterAgent> input) {
//				boolean flag = !UKDataContext.AgentStatusEnum.INCALL.toString().equals(input.getValue().getStatus()) && input.getValue().getUpd() != 0
//						&& input.getValue().isOffline()==false && input.getValue().getWorkstatus().equals(UKDataContext.WorkStatusEnum.CALLOUT.toString());
				boolean flag = !UKDataContext.AgentStatusEnum.INCALL.toString().equals(input.getValue().getStatus())
								&& !StringUtils.isBlank(orgi) && orgi.equals(input.getValue().getOrgi());
				if (flag) {
					count ++ ;
				}
			}

			@Override
			public void combine(Aggregator aggregator) {
				this.count += this.getClass().cast(aggregator).count;
			}

			@Override
			public Long aggregate() {
				if (count == 0) {
	                return (long) 0;
	            }
				return count ;
			}
			
		});
		return avgSalary;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countAiCallOutCache(String orgi,String ownerai,String actid) {
		/**
		 * 统计外呼并发总数
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallOutCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallOutNames>>count(), new AiCallOutFilterPredicate(orgi,ownerai,actid)) ;
		return names!=null ? names.intValue() : 0 ;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static long getAiUserCount(String orgi){
		IMap aiUserMap = (IMap<String, Object>) CacheHelper.getAiUserCacheBean().getCache() ;
		long count = (long) aiUserMap.aggregate(Aggregators.<Map.Entry<String, AiUser>>count(), new AiUserFilterPredicate(orgi)) ;
		return count;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static long getRobotToolsCount(){
		IMap robotToolMap = (IMap<String, Object>) CacheHelper.getRobotCacheBean().getCache() ;
		long count = (long) robotToolMap.aggregate(Aggregators.<Map.Entry<String, Object>>count()) ;
		return count;
	}
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static long getAiUserCount(){
		IMap aiUserMap = (IMap<String, Object>) CacheHelper.getAiUserCacheBean().getCache() ;
		long count = (long) aiUserMap.aggregate(Aggregators.<Map.Entry<String, AiUser>>count()) ;
		return count;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String getAiUserStat(){
		IMap aiUserMap = (IMap<String, Object>) CacheHelper.getAiUserCacheBean().getCache() ;
		return aiUserMap.getLocalMapStats().toString();
	}	
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String getRobotToolsStat(){
		IMap robotToolMap = (IMap<String, Object>) CacheHelper.getRobotCacheBean().getCache() ;
		return robotToolMap.getLocalMapStats().toString();
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String getCallCenterStat(){
		IMap callCenterMap = (IMap<String, Object>) CacheHelper.getCallCenterCacheBean().getCache() ;
		return callCenterMap.getLocalMapStats().toString();
	}
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String getCallOutNameStat(){
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallOutCacheBean().getCache() ;
		return callOutMap.getLocalMapStats().toString();
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int countForecastCallOutCache(String orgi,String ownerqueue,String actid) {
		/**
		 * 统计预测式外呼并发总数
		 */
		IMap callOutMap = (IMap<String, Object>) CacheHelper.getCallOutCacheBean().getCache() ;
		Long names = (Long) callOutMap.aggregate(Aggregators.<Map.Entry<String, CallOutNames>>count(), new ForecastCallOutFilterPredicate(orgi,ownerqueue,actid)) ;
		return names!=null ? names.intValue() : 0 ;
	}
}
